#ifndef __FILE_PROTO_H__
#define __FILE_PROTO_H__

#include "yid.h"
#include "lich_id.h"
#include "table_proto.h"
#include "fileinfo.h"
#include "fs_proto.h"
#include "chunk.h"
#include "plock.h"
#include "chunk_proto.h"
#include "volume_proto_eclog.h"
#include "cluster.h"
#include "lease.h"

#include "lich_ctx.h"
#include "lsv.h"
#include "token_bucket.h"
#include "lichstor.h"
#include "lock_table.h"
#include "table1.h"
#include "table2.h"
#include "profile.h"
#include "lich_qos.h"

/**
 * @file Volume proto Manager
 *
 * 每个卷有一个volume_proto_t结构，内含一个table1和table2实例。
 * table1管理vol/subvol chunk，table2管理raw chunk。
 *
 * @note 几个结构体里都有一个ltime字段，设置为0时，导致卷被重新加载，写错误时这样处理，读不需要
 * @note 对subvol，采用延迟加载的方式，以减少加载时间
 *
 * @todo 当卷较大时，table2耗用内存过多
 */

//lock1 --> lock2 --> lock3
/**
 * lock1   : volume ctl
 * lock2   : table1->fileinfo,table_proto,table_array
 * lock3.1 : for each subvol
 * lock3.2 : for each raw
 */
/**
 * volume proto / table1 / table2 struct graph by Gabe:
 *
 * ------+                        L1 first chunk(table1->table_proto)       L1 rest chunk array(table1->ext)
 *       |                        +-------------------------------+         +-------------------------------+    table1->table_array
 * table1|                        | info | bitmap |item1|item2|...| vol.x.0 | info | bitmap |item1|item2|...|    +-------------+
 *       |                        +-------------------------------+         +-------------------------------+    |    |    |...|
 * ------+                  .------------------------`     `-----------.                                         +-------------+
 *                         /        .-----------------------------------\-------------------------------------------`    |
 * ------+                 |       /                                    |       .----------------------------------------`
 *       | +-------------------------------+            +-------------------------------+                        table2->chunk_array
 * table2| | info | bitmap |item1|item2|...| subvol.x.0 | info | bitmap |item1|item2|...| subvol.x.1             +-----------------------+
 *       | +-------------------------------+            +-------------------------------+                        |    |    |    |    |...|
 * ------|           .-------`     `-------.                       .-------`     `-------.                       +-----------------------+
 *       |       +-----+                +-----+                +-----+               +-----+                       |    |     |    |
 * raw   |       | raw |  raw.x.0       | raw | raw.x.1        | raw | raw.x.n       | raw | raw.x.n+1             |    |     |    |
 *       |       +-----+                +-----+                +-----+               +-----+                       |    |     |    |
 * ------+         `-----------------------|----------------------|----------------------|-------------------------`    |     |    |
 *                                         `----------------------|----------------------|------------------------------`     |    |
 *                                                                `----------------------|------------------------------------`    |
 *                                                                                       `-----------------------------------------`
 */



/*

table1 / table2

@insert
@update
@check
@update_parent
@check_parent
@lock

 */

#define ANALY_AVG_UPDATE_COUNT (3)  //secend
typedef struct {
        uint64_t read_count;
        uint64_t write_count;
        uint64_t read_bytes;
        uint64_t write_bytes;
        time_t last_output;

        /* for each seconds */
        time_t last;
        int cur;
        uint64_t readps[ANALY_AVG_UPDATE_COUNT];
        uint64_t writeps[ANALY_AVG_UPDATE_COUNT];
        uint64_t readbwps[ANALY_AVG_UPDATE_COUNT];
        uint64_t writebwps[ANALY_AVG_UPDATE_COUNT];
} analy_t;

typedef struct {
        uint64_t read_count;
        uint64_t write_count;
        uint64_t read_used;
        uint64_t write_used;
        time_t last_output;

        time_t read_last;
        time_t write_last;

        int valid;
} latency_t;

typedef struct {
        sy_spinlock_t lock;
        uint64_t offset;
        uint32_t size;
        time_t ltime;

        sy_rwlock_t rwlock;
        uint32_t idx;
        uint64_t clock;
        void *buf;
} readahead_t;

#if 0
typedef struct {
        int valid;
        token_bucket_t bucket;
} bw_bucket_t;

typedef struct {
        int valid;
        token_bucket_t bucket;
} iops_bucket_t;
#endif


struct __volume_proto;

typedef struct __volume_proto_op_t {
        int (*load)(struct __volume_proto *volume_proto, const chkid_t *parent, const chkinfo_t *chkinfo);
        int (*post_load)(struct __volume_proto *volume_proto);
        void (*destroy)(struct __volume_proto *volume_proto);
} volume_proto_op_t;

typedef enum __volume_proto_status_t {
        VOLUME_PROTO_STATUS_INIT = 0,
        VOLUME_PROTO_STATUS_PRE_LOAD,
        VOLUME_PROTO_STATUS_LOAD1,       // raw volume is ready
        VOLUME_PROTO_STATUS_LOAD2,       // lvs volume is ready
        VOLUME_PROTO_STATUS_DROP,
} volume_proto_status_t;

typedef struct {
        int (*snapshot_create)(struct __volume_proto *, const char *name, int p, const char *site);
        int (*snapshot_list)(struct __volume_proto *, void *buf, int *len);
        int (*snapshot_lookup)(struct __volume_proto *, const char *name, chkinfo_t *chkinfo);
        int (*snapshot_check)(struct __volume_proto *, const char *name);
        int (*snapshot_remove)(struct __volume_proto *, const char *name, int force);
        int (*snapshot_protect)(struct __volume_proto *, const int on);
        int (*snapshot_cleanup)(struct __volume_proto *);
        int (*snapshot_last)(struct __volume_proto *, nid_t *nid, fileid_t *fileid, char *name, uint64_t *snap_version);
        int (*snapshot_rollback)(struct __volume_proto *, const char *name);
        int (*snapshot_rollback_bh1)(struct __volume_proto *, chkid_t *);
        int (*snapshot_rollback_bh2)(struct __volume_proto *, fileid_t *);
        int (*snapshot_rollback_bh)(struct __volume_proto *, buffer_t *);
        int (*snapshot_cleanup_chunk)(const nid_t *srcnid, const fileid_t *srcid,
                                      const nid_t *distnid, const fileid_t *distid, int idx, uint64_t max);
        int (*snapshot_cleanup_bh2)(struct __volume_proto *, const char *name);
} volume_proto_snapshot_op_t;

typedef struct {
        int inited;

        uint32_t chknum;

        int has_auto_snap;
        uint64_t auto_snap;
        chkinfo_t *auto_snap_chkinfo;

        uint64_t from_snap;
        chkinfo_t *from_snap_chkinfo;

        // list of snap_t, used by auto-save process
        struct list_head root_snap_list;

        struct list_head auto_snap_list;

        // list of snap_t, used by snapshot-reading process
        struct list_head downstream_snap_list;

        // list of snap_t, used by snapshot-reading process
        struct list_head cross_snap_list;

        // struct list_head read_snap_list;

        struct {
                uint64_t chknum;
                uint64_t allocate;
                uint64_t update_meta;

                uint64_t snap_exist;
                uint64_t snap_read;
                uint64_t vol_read;
                uint64_t vol_write;
                uint64_t auto_read;
                uint64_t auto_write;
        } stat;

        // private
        char __auto_snap_chkinfo[CHKINFO_MAX];
        char __from_snap_chkinfo[CHKINFO_MAX];
} rollback_ctx_t;

typedef struct {
        struct {
                uint64_t chknum;
                uint64_t clone;
                uint64_t snap_read;
                uint64_t vol_write;
                uint64_t vol_create;
                uint64_t vol_createwith;
        } stat;
} flat_ctx_t;


typedef struct {
        count_list_t connect_list;
        plock_t rwlock;
} connect_t;

typedef struct __volume_proto {
        chkid_t chkid;
        connect_t connect;
        time_t ltime;
        time_t uptime;
        uint32_t magic;

        analy_t analysis;
        latency_t latency;
        //readahead_t readahead;
        token_bucket_t iops_bucket;
        token_bucket_t bw_bucket;

        table1_t table1;
        table2_t table2;

        struct chunk_proto_ops chunk_ops;
        
        lease_t lease;
        uuid_t snapshot_lock_uuid;
        char destroy;
        eclog_t **eclog;
        int ramdisk_fd;

        volume_proto_status_t status;
        volume_proto_op_t ops;

        rollback_ctx_t rollback_ctx;
        flat_ctx_t flat_ctx;

        qos_t qos;


#if ENABLE_PROFILE
        profile_t profile_io_write;
        profile_t profile_chunk_create;
        profile_t profile_chunk_create2;
#endif

        int (*setattr)(struct __volume_proto *, fileinfo_t *fileinfo, const setattr_t *setattr);
        int (*getattr)(struct __volume_proto *, fileinfo_t *fileinfo);

        int (*needreload)(struct __volume_proto *);
        //int (*reload)(struct __volume_proto **, const char *pool, const fileid_t *parent, const chkinfo_t *chkinfo);

        int (*cleanup)(struct __volume_proto *);
        int (*cleanup_bh1)(struct __volume_proto *, const chkid_t *chkid);
        int (*cleanup_bh2)(struct __volume_proto *);
        int (*suicide)(struct __volume_proto *);

        int (*stat)(struct __volume_proto *, filestat_t *, off_t, size_t);
        int (*move)(struct __volume_proto *, const nid_t *nid, int count);

        int (*iscsiConnection)(struct __volume_proto *, const nid_t *peer, void *list, int *count);
        int (*iscsiConnect)(struct __volume_proto *, const nid_t *peer, const char *addr);
        int (*iscsiDisconnect)(struct __volume_proto *, const nid_t *peer, const char *addr);

        int (*xattr_set)(struct __volume_proto *volume_proto, const char *key, const char *value,
                        uint32_t valuelen, int flag);
        int (*xattr_get)(struct __volume_proto *volume_proto, const char *key, char *value, int *valuelen);
        int (*xattr_list)(struct __volume_proto *volume_proto, char *buf, int *buflen);
        int (*xattr_remove)(struct __volume_proto *volume_proto, const char *key);

        int (*chunk_getinfo)(struct __volume_proto *, const chkid_t *chkid, chkinfo_t *chkinfo);
        int (*chunk_iterator1)(struct __volume_proto *, func2_t func2, void *_arg);
        int (*chunk_iterator2)(struct __volume_proto *, func2_t func2, void *_arg, uint64_t idx);
        int (*chunk_unintact1)(struct __volume_proto *, func3_t func3, void *_arg);
        int (*chunk_unintact2)(struct __volume_proto *, func3_t func3, void *_arg, uint64_t idx, int deep);

        int (*chunk_set)(struct __volume_proto *, const chkid_t *chkid, const nid_t *nid, int status);
        int (*chunk_sync)(struct __volume_proto *, const chkid_t *chkid, int *oflags);
        int (*chunk_check)(struct __volume_proto *volume_proto, const chkid_t *, int *oflags);
        int (*chunk_move)(struct __volume_proto *, const chkid_t *chkid, const nid_t *nid, int count);
        int (*chunk_localize)(struct __volume_proto *, const chkid_t *chkid);

        int (*chunk_allocate)(struct __volume_proto *, const chkid_t *chkid, int chknum, int fill);
        int (*chunk_cleanup)(struct __volume_proto *, const chkid_t *chkid, const nid_t *_nid, uint64_t meta_version);
        int (*chunk_update)(struct __volume_proto *, const chkinfo_t *chkinfo, const nid_t *owner, uint64_t info_version);
        int (*chunk_reject)(struct __volume_proto *, const chkid_t *chkid, const nid_t *bad, chkinfo_t *chkinfo);
        int (*chunk_extend)(struct __volume_proto *, const int idx);

        int (*snapshot_create)(struct __volume_proto *, const char *name, int p, const char *site, int force);
        int (*snapshot_remove)(struct __volume_proto *, const char *name, int force);
        int (*snapshot_listopen)(struct __volume_proto *, const char *uuid);
        int (*snapshot_list)(struct __volume_proto *, const char *uuid, uint64_t offset, void *de, int *delen);
        int (*snapshot_listclose)(struct __volume_proto *, const char *uuid);
        int (*snapshot_lookup)(struct __volume_proto *, const char *name, chkinfo_t *chkinfo);
        int (*snapshot_check)(struct __volume_proto *, const char *name);
        int (*snapshot_protect)(struct __volume_proto *, const snap_protect_param_t on);
        int (*snapshot_updateparent)(struct __volume_proto *, const char *name, const uint64_t from);
        int (*snapshot_setfrom)(struct __volume_proto *, const uint64_t from);
        int (*snapshot_last)(struct __volume_proto *, nid_t *nid, fileid_t *fileid, char *name, uint64_t *snap_version);
        int (*snapshot_prev)(struct __volume_proto *, const chkid_t *chkid, chkid_t *prev, char *name, uint64_t *snap_version);
        int (*snapshot_isempty)(struct __volume_proto *, int *empty);

        // 读取快照，可能涉及遍历多个快照，需要调度到快照所在的卷控制器上
        int (*snapshot_read)(struct __volume_proto *, const io_t *io, buffer_t *buf);

        int (*snapshot_read_meta)(struct __volume_proto *, const io_t *io, const char *snap, buffer_t *buf);
        int (*lower_read)(struct __volume_proto *, const io_t *io, buffer_t *buf);

        // int (*snapshot_cleanup)(struct __volume_proto *);

        // method 1: 标记删除
        int (*snapshot_cleanup_chunk)(const nid_t *srcnid, const fileid_t *srcid,
                                      const nid_t *distnid, const fileid_t *distid,
                                      int idx, uint64_t max, const ec_t *ec);
        int (*snapshot_cleanup_bh2)(struct __volume_proto *, const char *name);

        // method 2: 直接删除
        int (*snapshot_cleanup_direct)(struct __volume_proto *, const char *name);

        int (*snapshot_rollback)(struct __volume_proto *, const char *name);
        int (*snapshot_rollback_bh1)(struct __volume_proto *, chkid_t *);
        int (*snapshot_rollback_bh2)(struct __volume_proto *, fileid_t *);
        int (*snapshot_rollback_bh)(struct __volume_proto *, buffer_t *);

        int (*snapshot_flat)(struct __volume_proto *volume_proto, int on);
        int (*snapshot_flat_bh1)(struct __volume_proto *volume_proto, int idx, int thin);

        int (*vfm_cleanup)(struct __volume_proto *volume_proto, const chkid_t *tid);
        int (*vfm_set_dangerously)(struct __volume_proto *volume_proto, const chkid_t *chkid, const vfm_t *_vfm);
        int (*vfm_add)(struct __volume_proto *volume_proto, const nid_t *nid, int count);
        int (*vfm_get)(struct __volume_proto *volume_proto, const chkid_t *chkid, vfm_t *_vfm);
        int (*vfm_stat)(struct __volume_proto *volume_proto, int *count);

} volume_proto_t;

/*from volume_proto.c*/
int volume_proto_io_split(volume_proto_t *volume_proto, const io_t *_io,
                buffer_t *buf, chunk_io_t *ios, int *_segs);

int volume_proto_load(volume_proto_t **_volume_proto, const char *pool, const chkid_t *parent, const chkinfo_t *chkinfo);
int volume_proto_renew(volume_proto_t *volume_proto);
int volume_proto_post_load(volume_proto_t *volume_proto);

void volume_proto_destroy(volume_proto_t *volume_proto);
int volume_proto_post_destroy(volume_proto_t *volume_proto);

int volume_proto_info(volume_proto_t *volume_proto);

int volume_proto_check_ready(volume_proto_t *volume_proto);

int volume_proto_chunk_check(volume_proto_t *volume_proto, const chkid_t *chkid, int op, int *oflags);
int volume_proto_chunk_exist(volume_proto_t *volume_proto, const chkid_t *chkid, int *exist);

int volume_proto_newchunk(volume_proto_t *volume_proto, const chkid_t *chkid, const buffer_t *buf);
int volume_proto_discard(volume_proto_t *volume_proto, const chkid_t *chkid);
int volume_proto_batch_discard(volume_proto_t *volume_proto, const chkid_t **chkid, int n_chks);

int volume_proto_chunk_pre_read(volume_proto_t *volume_proto, chunk_io_t *chunk_io);
int volume_proto_chunk_pre_write(volume_proto_t *volume_proto, io_opt_t *io_opt, chunk_io_t *chunk_io);
int volume_proto_chunk_reset(volume_proto_t *volume_proto, const chkid_t *chkid);
int volume_proto_chunk_post_io(volume_proto_t *volume_proto, const chkid_t *chkid,
                               const chkinfo_t *chkinfo, const chkstat_t *chkstat, uint64_t clock);

int volume_proto_chunk_write(volume_proto_t *volume_proto, io_opt_t *io_opt,
                             chunk_io_t *chunk_io);
int volume_proto_chunk_read(volume_proto_t *volume_proto, chunk_io_t *chunk_io);

/* from volume_proto_inf.c */
int volume_proto_read(volume_proto_t *volume_proto, const io_t *io, buffer_t *buf);
int volume_proto_write(volume_proto_t *volume_proto, const io_t *io, const buffer_t *buf);
int volume_proto_unmap(volume_proto_t *volume_proto, const io_t *io);

/* from volume_proto_io.c */
int volume_proto_write_raw(volume_proto_t *volume_proto, io_opt_t *io_opt, const io_t *io, const buffer_t *buf);
int volume_proto_truncate(volume_proto_t *volume_proto, uint64_t offset, uint32_t size);
int volume_proto_unmap_raw(volume_proto_t *volume_proto, io_opt_t *io_opt, const io_t *io);

int volume_proto_read_raw(volume_proto_t *volume_proto, const io_t *io, buffer_t *buf);

/*from volume_proto_io.c*/
int volume_proto_table_read(volume_proto_t *volume_proto, const chkid_t * chkid,
        buffer_t *buf, size_t size, off_t offset);
int volume_proto_table_write(volume_proto_t *volume_proto, const chkid_t *chkid,
        const buffer_t *buf, size_t size, off_t offset);

/*from volume_proto_ec.c*/
int volume_proto_ec_read(volume_proto_t *volume_proto, const io_t *io, buffer_t *buf);
int volume_proto_ec_write(volume_proto_t *volume_proto, io_opt_t *io_opt, const io_t *io, const buffer_t *buf);

/*from volume_proto_rep.c*/
int volume_proto_rep_read(volume_proto_t *volume_proto, const io_t *io, buffer_t *buf);
int volume_proto_rep_write(volume_proto_t *volume_proto, io_opt_t *io_opt, const io_t *io, const buffer_t *buf);

/*from volume_proto_analysis.c*/
int volume_proto_analysis_init(volume_proto_t *volume_proto);
int volume_proto_analysis_record(volume_proto_t *volume_proto, int len, int op);
void volume_proto_analysis_destroy(volume_proto_t *volume_proto);

/*from volume_proto_latency.c*/
int volume_proto_latency_init(volume_proto_t *volume_proto);
int volume_proto_latency_begin(volume_proto_t *volume_proto, time_t *begin, int *record, int op);
int volume_proto_latency_record(volume_proto_t *volume_proto, time_t begin, int record, int op);
void volume_proto_latency_destroy(volume_proto_t *volume_proto);

/*from volume_proto_snapshot.c*/
int volume_proto_snapshot_init(volume_proto_t *volume_proto);

int volume_proto_snapshot_check(volume_proto_t *volume_proto, const chkid_t *chkid,
                              uint64_t snap_version, int op);

int volume_proto_snapshot_buildlist(volume_proto_t *volume_proto, uint64_t src, uint64_t dst,
                                    int bottomup, struct list_head *list);

/**
 * 读快照
 *
 * @param volume_proto
 * @param io
 * @param buf
 * @return
 */
int volume_proto_snapshot_read(volume_proto_t *volume_proto, const io_t *io, buffer_t *buf);

/**
 * 读某一快照
 *
 * @param snapnid 快照控制器所在节点
 * @param io
 * @param buf
 * @param peek
 * @return
 */
int volume_proto_snapshot_read_remote(const nid_t *snapnid, const io_t *io, buffer_t *buf, int peek);

/**
 * clone卷的读快照
 *
 * @param volume_proto
 * @param chkid
 * @param buf
 * @param _size
 * @param _offset
 * @return
 */
int volume_proto_snapshot_chunk_redirect(volume_proto_t *volume_proto, const chkid_t *chkid,
                                         buffer_t *buf, int _size, int _offset, BOOL fill);

int volume_proto_snapshot_chunk_clone(volume_proto_t *volume_proto, const chkid_t *chkid, int thin);
// int volume_proto_snapshot_chunk_clone_remote(volume_proto_t *volume_proto, const chkid_t *chkid);

int volume_proto_snapshot_flat(volume_proto_t *volume_proto, int idx);
int volume_proto_snapshot_flat_bh1(volume_proto_t *volume_proto, int idx, int thin);

// 删除快照数据移动的源
int volume_proto_snapshot_cleanup_bh_src(volume_proto_t *volume_proto,
                                         const char *name, chkinfo_t *chkinfo, uint64_t *snap_version);

// 删除快照数据移动的目标，即要删除快照的父快照
int volume_proto_snapshot_cleanup_bh_dist(volume_proto_t *volume_proto,
                                          const fileid_t *fileid, nid_t *distnid, fileid_t *distid);

int volume_proto_snapshot_diff(volume_proto_t *volume_proto, const fileid_t *fileid,
                               const fileid_t *snapdst, buffer_t *buf, size_t size, off_t offset);

int volume_proto_snapshot_lsv_init(volume_proto_t *volume_proto);

/*from table1.c*/
int table1_init(table1_t *table1, const char *pool, const fileid_t *fileid,
                const fileid_t *parent, void *volume_proto);
void table1_destroy(table1_t *table1);

int table1_cleanup(table1_t *table1);

int table1_load(table1_t *table1, const chkid_t *parent, const chkinfo_t *chkinfo);
int table1_iterator_callback(const void *value, int loc, int idx, void *ctx);

/*from table2.c*/
int table2_ec_wrlock(table2_t *table2, const chkid_t *chkid);
int table2_ec_rdlock(table2_t *table2, const chkid_t *chkid);
void table2_ec_unlock(table2_t *table2, const chkid_t *chkid);

int table2_init(table2_t *table2, table1_t *table1);
void table2_destroy(table2_t *table2);

int table2_cleanup(table2_t *table2);
int table2_iterator_callback(const void *value, int loc, int idx, void *ctx);

// ----------------------------------------------------------------------------------
// LSV log structured volume format
// ----------------------------------------------------------------------------------

/* from volume_proto_io_lsv.c */
int lsv_volume_proto_write(volume_proto_t *volume_proto, const io_t *io, const buffer_t *buf);
int lsv_volume_proto_read(volume_proto_t *volume_proto, const io_t *io, buffer_t *buf);

// int write_data_buffer(lsv_volume_proto_t *lsv_info, const io_t *io, buffer_t *buf);
int volume_proto_mem_append_io(lsv_volume_proto_t *lsv_info, const io_t *io, buffer_t *buf);
// int volume_proto_append_io(lsv_volume_proto_t *lsv_info, const io_t *io, buffer_t *buf, int flag);

// ----------------------------------------------------------------------------------
// ROW2 volume format
// ----------------------------------------------------------------------------------

/* from volume_proto_io_row2.c */
int row2_volume_proto_write(volume_proto_t *volume_proto, const io_t *io, const buffer_t *buf);
int row2_volume_proto_read(volume_proto_t *volume_proto, const io_t *io, buffer_t *buf);
void row2_data_cow_callback(uint8_t * dataptr);

// --------------------------- INTERNALS ----------------------------
// --------------------------- INTERNALS ----------------------------

int __table1_chunk_newinfo(table1_t *table1, const chkid_t *chkid, chkinfo_t *chkinfo);

int __table1_insert(table1_t *table1, const fileid_t *parent, const chkid_t *tid, const char *item, int len);

int __table1_load_table2(table1_t *table1, const chkinfo_t *__chkinfo,
                         table_proto_t **_table_proto, int new, volume_proto_t *volume_proto);

int __table1_get_table_proto_l1(table1_t *table1, table_proto_t **_table, const chkid_t *top_chkid);

int __table1_update_table_proto(const table1_t *table1, table_proto_t *table_proto,
                                const chkinfo_t *new_chkinfo, const chkstat_t *new_chkstat);

/**
 * L1 ext and L2 table proto
 *
 * @param table1
 * @param chkid
 * @param volume_proto
 * @param is_subvol
 * @return
 */
int __table1_create_table_proto(table1_t *table1, volume_proto_t *volume_proto, const chkid_t *chkid, int is_subvol);

int __table1_update_ext_info(table1_t *table1, const chkid_t *chkid,
                             const chkinfo_t *new_chkinfo, const chkstat_t *new_chkstat);

int __table1_ensure_l1(table1_t *table1, const chkid_t *tid, volume_proto_t *volume_proto);

#endif
